﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Language.Intellisense;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.Text;
using LuaLanguageExtension.Parsing;

namespace LuaLanguageExtension.Intellisense.CompletionSets
{
    class CommonCompletionSet : Microsoft.VisualStudio.Language.Intellisense.CompletionSet 
    {
        public CommonCompletionSet(ObjectModelIntellisenseAcrossData acrossData)
            : base("Common Completions", "Common Completions", null, null, Enumerable.Empty<Completion>())
        {
            this.acrossData = acrossData;
            //this.completionDictionary = completionDictionary;
            this.acrossData.Completions.CollectionChanged += delegate
            {
                SelectBestMatch();
            };
            this.completions = new ObservableCollection<Completion>();

            base.ApplicableTo = this.acrossData.TrackingSpan;

            AssignCompletionsToPresenter(this.acrossData.Completions);
        }

        public override void  SelectBestMatch()
        {
            string prefix = GetPrefix().ToLower();
            if (prefix.Length > 0 && false)
            {
                var filteredCompletions = this.acrossData.Completions.Where(c => c.DisplayText.ToLower().Contains(prefix.ToLower()));
                AssignCompletionsToPresenter(filteredCompletions);
            }
            else
            {
                AssignCompletionsToPresenter(this.acrossData.Completions);
            }

            //First try to find completion wich starts with prefix
            Completion completion = Completions.FirstOrDefault(c => c.DisplayText.ToLower().StartsWith(prefix));

            //If no - try to find completion wich contains prefix
            if (completion == null) completion = Completions.FirstOrDefault(c => c.DisplayText.ToLower().Contains(prefix));

            bool select = completion != null;
            //If no - select first completion
            if (completion == null) completion = Completions.FirstOrDefault();

            if (completion != null) base.SelectionStatus = new CompletionSelectionStatus(completion, select,true);
        }

        public override IList<Completion> Completions
        {
            get { return completions; }
        }

        private void AssignCompletionsToPresenter(IEnumerable<Completion> newCompletions)
        {
            var curComp = Completions.Select(c => c.DisplayText).ToList();
            var newComp = newCompletions.Select(c => c.DisplayText).ToList();

            var compNameToAdd = newComp.Except(curComp).ToList();
            var compNameToDelete = curComp.Except(newComp).ToList();


            var compToAdd = newCompletions.Where(c => compNameToAdd.Contains(c.DisplayText)).ToList();
            var compToDelete = Completions.Where(c => compNameToDelete.Contains(c.DisplayText)).ToList();

            foreach (var item in compToAdd) this.Completions.Add(item);
            foreach (var item in compToDelete) this.Completions.Remove(item);
        }

        /// <summary>
        /// Calculates the prefix used to filter and position the completion list
        /// </summary>
        /// <returns></returns>
        private string GetPrefix()
        {
            var prefix = acrossData.TrackingSpan.GetText(acrossData.TrackingSpan.TextBuffer.CurrentSnapshot);
            prefix = prefix.Trim(' ', '\t');
            return prefix;
        }

        //private ITrackingSpan filterSpan;
        //private ObservableCollection<Completion> completionDictionary;
        private ObjectModelIntellisenseAcrossData acrossData;
        private ObservableCollection<Completion> completions;
    }
}
